home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / doom / quake2.zip / TF1_2SRC.ZIP / QUAKE / FORTRESS / SOURCE / WEAPONS.QC < prev    next >
Text File  |  1996-09-10  |  47KB  |  2,041 lines

  1. /*
  2.     Heavily Modified for TeamFortress V1.2
  3.     Robin Walker, John Cook
  4. */
  5. void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
  6. void (entity targ, entity inflictor, entity attacker, float damage, float T_flags) TF_T_Damage;
  7. void () player_run;
  8. void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage;
  9. void(vector org, vector vel, float damage) SpawnBlood;
  10. void() SuperDamageSound;
  11.  
  12. // TeamFortress Impulse Commands
  13. void() TeamFortress_ChangeClass;
  14. void() TeamFortress_Inventory;
  15. void() TeamFortress_ShowTF;
  16. void() TeamFortress_SniperWeapon;
  17. void() TeamFortress_AssaultWeapon;
  18. void() TeamFortress_PrimeGrenade;
  19. void() TeamFortress_ThrowGrenade;
  20. void() TeamFortress_DetonatePipebombs;
  21. void() PipebombTouch;
  22. // TeamFortress Pre-Impulse Commands
  23. void(float scanrange) TeamFortress_Scan;
  24. void(float timer) TeamFortress_SetDetpack;
  25. void(float helpindex) TeamFortress_Help;
  26. void(float tflag) TeamFortress_Toggle;
  27. void(float skinno) TeamFortress_Multiskin;
  28. void(float funcno) TeamFortress_Team;
  29.  
  30. // Multiskin Functions
  31. void() Multiskin_NextSkin;
  32. void() Multiskin_PrevSkin;
  33.  
  34. // BioInfection functions
  35. void() BioInfection_Decay;
  36. void() BioInfection_MonsterDecay;
  37. void() player_touch;
  38.  
  39. // PC_UNDEFINED viewing functions
  40. void() TF_MovePlayer;
  41.  
  42. // called by worldspawn
  43. void() W_Precache =
  44. {
  45.     precache_sound ("weapons/r_exp3.wav");    // new rocket explosion
  46.     precache_sound ("weapons/rocket1i.wav");// spike gun
  47.     precache_sound ("weapons/sgun1.wav");
  48.     precache_sound ("weapons/guncock.wav");    // player shotgun
  49.     precache_sound ("weapons/ric1.wav");    // ricochet (used in c code)
  50.     precache_sound ("weapons/ric2.wav");    // ricochet (used in c code)
  51.     precache_sound ("weapons/ric3.wav");    // ricochet (used in c code)
  52.     precache_sound ("weapons/spike2.wav");    // super spikes
  53.     precache_sound ("weapons/tink1.wav");    // spikes tink (used in c code)
  54.     precache_sound ("weapons/grenade.wav");    // grenade launcher
  55.     precache_sound ("weapons/bounce.wav");    // grenade bounce
  56.     precache_sound ("weapons/shotgn2.wav");    // super shotgun
  57.     if (!(IS_NET_SERVER))
  58.         precache_sound ("weapons/sniper.wav");    // sniper rifle
  59. };
  60.  
  61. float() crandom =
  62. {
  63.     return 2*(random() - 0.5);
  64. };
  65.  
  66. /*
  67. ================
  68. W_FireAxe
  69. ================
  70. */
  71. void() W_FireAxe =
  72. {
  73.     local    vector    source;
  74.     local    vector    org;
  75.  
  76.     source = self.origin + '0 0 16';
  77.     traceline (source, source + v_forward*64, FALSE, self);
  78.     if (trace_fraction == 1.0)
  79.         return;
  80.     
  81.     org = trace_endpos - v_forward*4;
  82.  
  83.     if (trace_ent.takedamage)
  84.     {
  85.         trace_ent.axhitme = 1;
  86.         SpawnBlood (org, '0 0 0', 20);
  87.         TF_T_Damage (trace_ent, self, self, 20, TF_TD_NOTTEAM);
  88.     }
  89.     else
  90.     {    // hit wall
  91.         sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
  92.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  93.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  94.         WriteCoord (MSG_BROADCAST, org_x);
  95.         WriteCoord (MSG_BROADCAST, org_y);
  96.         WriteCoord (MSG_BROADCAST, org_z);
  97.     }
  98. };
  99.  
  100. /*
  101. ================
  102. W_FireMedikit  
  103. ================
  104. */
  105.  
  106. void() W_FireMedikit =
  107. {
  108.     local    vector    source;
  109.     local    vector    org;
  110.     local    float healam;    
  111.  
  112.     source = self.origin + '0 0 16';
  113.     traceline (source, source + v_forward*64, FALSE, self);
  114.     if (trace_fraction == 1.0)
  115.         return;
  116.     
  117.     org = trace_endpos - v_forward*4;
  118.  
  119.     if (trace_ent.takedamage)
  120.     {
  121.         if (trace_ent.classname == "player")
  122.         {
  123.             if ((trace_ent.team == self.team) || (coop))
  124.             {
  125.                 healam = NIT_MEDIKIT_HEAL;
  126.                 if (self.ammo_medikit < healam)
  127.                     healam = self.ammo_medikit;
  128.  
  129.                 // check if the healed player is infected
  130.                 if (trace_ent.tfstate & TFSTATE_INFECTED)
  131.                 {
  132.                     healam = rint(trace_ent.health / 2);
  133.  
  134.                     // remove the infection
  135.                     trace_ent.tfstate = trace_ent.tfstate - (trace_ent.tfstate & TFSTATE_INFECTED);
  136.  
  137.                     // some damage is caused (because of the use of leeches!)
  138.                     // remove half their remaining health
  139.                     T_Damage(trace_ent, self, self, healam);
  140.                     SpawnBlood(org, '0 0 0', 30);
  141.  
  142.                     sprint(trace_ent, "Your infection is cured!\n");
  143.                     sprint(self, "You have healed ");
  144.                     sprint(self, trace_ent.netname);
  145.                     sprint(self, " of the infection.\n");
  146.  
  147.                     return;
  148.                 }
  149.  
  150.                 if (healam > 0 && trace_ent.health < trace_ent.max_health)
  151.                 {
  152.                     sound(trace_ent, CHAN_WEAPON, "items/r_item1.wav", 1, ATTN_NORM);
  153.                     self.ammo_medikit = self.ammo_medikit - healam;
  154.                     trace_ent.axhitme = 1;
  155.                     SpawnBlood (org, '0 0 0', 20);
  156.                     T_Heal(trace_ent, healam, 0);
  157.                 }
  158.             }
  159.           }
  160.     }
  161.     else
  162.     {    // hit wall
  163.         sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
  164.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  165.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  166.         WriteCoord (MSG_BROADCAST, org_x);
  167.         WriteCoord (MSG_BROADCAST, org_y);
  168.         WriteCoord (MSG_BROADCAST, org_z);
  169.     }
  170. };
  171.  
  172. /*
  173. ================
  174. W_FireBioweapon
  175. ================
  176. */
  177.  
  178. void() W_FireBioweapon =
  179. {
  180.     local    vector    source;
  181.     local    vector    org;
  182.     local    float healam;    
  183.  
  184.     local     entity BioInfection;
  185.  
  186.     source = self.origin + '0 0 16';
  187.     traceline (source, source + v_forward*64, FALSE, self);
  188.     if (trace_fraction == 1.0)
  189.         return;
  190.     
  191.     org = trace_endpos - v_forward*4;
  192.  
  193.     if (trace_ent.takedamage)
  194.     {
  195.         if (trace_ent.classname == "player")
  196.         {
  197.             trace_ent.axhitme = 1;
  198.             SpawnBlood (org, '0 0 0', 20);
  199.             T_Damage (trace_ent, self, self, 10);
  200.  
  201.             if (trace_ent.playerclass == PC_MEDIC)
  202.                 return;
  203.  
  204.             trace_ent.tfstate = trace_ent.tfstate | TFSTATE_INFECTED;
  205.  
  206.             BioInfection = spawn ();
  207.             BioInfection.classname = "timer";
  208.             BioInfection.owner = trace_ent;
  209.             BioInfection.nextthink = time + 2;
  210.             BioInfection.think = BioInfection_Decay;
  211.             BioInfection.enemy = self;
  212.  
  213.             BioInfection.tfstate = TFSTATE_ALTKILL;
  214.             BioInfection.altkillweapon = AK_BIOWEAPON;
  215.  
  216.             trace_ent.touch = player_touch;
  217.  
  218.         }
  219.         else if (trace_ent.flags == FL_MONSTER)
  220.         {
  221.             if (trace_ent.classname == "monster_zombie")
  222.             {
  223.                 // zombie slayer!
  224.                 T_Damage (trace_ent, self, self, 200);
  225.             }
  226.  
  227.             trace_ent.axhitme = 1;
  228.             SpawnBlood(org, '0 0 0', 20);
  229.             T_Damage (trace_ent, self, self, 10);
  230.  
  231.             BioInfection = spawn ();
  232.             BioInfection.classname = "timer";
  233.             BioInfection.nextthink = time + 2;
  234.             BioInfection.think = BioInfection_MonsterDecay;
  235.             BioInfection.owner = self;
  236.             BioInfection.enemy = trace_ent;
  237.         }
  238.         else // must be a switch
  239.         {
  240.             trace_ent.axhitme = 1;
  241.             SpawnBlood (org, '0 0 0', 30);
  242.             T_Damage(trace_ent, self, self, 40);
  243.         }
  244.     }
  245.     else
  246.     {    // hit wall
  247.         sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
  248.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  249.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  250.         WriteCoord (MSG_BROADCAST, org_x);
  251.         WriteCoord (MSG_BROADCAST, org_y);
  252.         WriteCoord (MSG_BROADCAST, org_z);
  253.     }
  254. };
  255.  
  256.  
  257. //============================================================================
  258.  
  259.  
  260. vector() wall_velocity =
  261. {
  262.     local vector    vel;
  263.     
  264.     vel = normalize (self.velocity);
  265.     vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
  266.     vel = vel + 2*trace_plane_normal;
  267.     vel = vel * 200;
  268.     
  269.     return vel;
  270. };
  271.  
  272.  
  273. /*
  274. ================
  275. SpawnMeatSpray
  276. ================
  277. */
  278. void(vector org, vector vel) SpawnMeatSpray =
  279. {
  280.     local    entity missile, mpuff;
  281.     local    vector    org;
  282.  
  283.     missile = spawn ();
  284.     missile.owner = self;
  285.     missile.movetype = MOVETYPE_BOUNCE;
  286.     missile.solid = SOLID_NOT;
  287.  
  288.     makevectors (self.angles);
  289.  
  290.     missile.velocity = vel;
  291.     missile.velocity_z = missile.velocity_z + 250 + 50*random();
  292.  
  293.     missile.avelocity = '3000 1000 2000';
  294.     
  295. // set missile duration
  296.     missile.nextthink = time + 1;
  297.     missile.think = SUB_Remove;
  298.  
  299.     setmodel (missile, "progs/zom_gib.mdl");
  300.     setsize (missile, '0 0 0', '0 0 0');        
  301.     setorigin (missile, org);
  302. };
  303.  
  304. /*
  305. ================
  306. SpawnBlood
  307. ================
  308. */
  309. void(vector org, vector vel, float damage) SpawnBlood =
  310. {
  311.     particle (org, vel*0.1, 73, damage*2);
  312. };
  313.  
  314. /*
  315. ================
  316. spawn_touchblood
  317. ================
  318. */
  319. void(float damage) spawn_touchblood =
  320. {
  321.     local vector    vel;
  322.  
  323.     vel = wall_velocity () * 0.2;
  324.     SpawnBlood (self.origin + vel*0.01, vel, damage);
  325. };
  326.  
  327.  
  328. /*
  329. ================
  330. SpawnChunk
  331. ================
  332. */
  333. void(vector org, vector vel) SpawnChunk =
  334. {
  335.     particle (org, vel*0.02, 0, 10);
  336. };
  337.  
  338. /*
  339. ==============================================================================
  340.  
  341. MULTI-DAMAGE
  342.  
  343. Collects multiple small damages into a single damage
  344.  
  345. ==============================================================================
  346. */
  347.  
  348. entity    multi_ent;
  349. float    multi_damage;
  350.  
  351. void() ClearMultiDamage =
  352. {
  353.     multi_ent = world;
  354.     multi_damage = 0;
  355. };
  356.  
  357. void() ApplyMultiDamage =
  358. {
  359.     if (!multi_ent)
  360.         return;
  361.     TF_T_Damage (multi_ent, self, self, multi_damage, TF_TD_NOTTEAM);
  362. };
  363.  
  364. void(entity hit, float damage) AddMultiDamage =
  365. {
  366.     if (!hit)
  367.         return;
  368.     
  369.     if (hit != multi_ent)
  370.     {
  371.         ApplyMultiDamage ();
  372.         multi_damage = damage;
  373.         multi_ent = hit;
  374.     }
  375.     else
  376.         multi_damage = multi_damage + damage;
  377. };
  378.  
  379. /*
  380. ==============================================================================
  381.  
  382. BULLETS
  383.  
  384. ==============================================================================
  385. */
  386.  
  387. /*
  388. ================
  389. TraceAttack
  390. ================
  391. */
  392. void(float damage, vector dir) TraceAttack =
  393. {
  394.     local    vector    vel, org;
  395.     
  396.     vel = normalize(dir + v_up*crandom() + v_right*crandom());
  397.     vel = vel + 2*trace_plane_normal;
  398.     vel = vel * 200;
  399.  
  400.     org = trace_endpos - dir*4;
  401.  
  402.     if (trace_ent.takedamage)
  403.     {
  404.         SpawnBlood (org, vel*0.2, damage);
  405.         AddMultiDamage (trace_ent, damage);
  406.     }
  407.     else
  408.     {
  409.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  410.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  411.         WriteCoord (MSG_BROADCAST, org_x);
  412.         WriteCoord (MSG_BROADCAST, org_y);
  413.         WriteCoord (MSG_BROADCAST, org_z);
  414.     }
  415. };
  416.  
  417. /*
  418. ================
  419. FireBullets
  420.  
  421. Used by shotgun, super shotgun, assault cannon, and enemy soldier firing
  422. Go to the trouble of combining multiple pellets into a single damage call.
  423. ================
  424. */
  425. void(float shotcount, vector dir, vector spread) FireBullets =
  426. {
  427.     local    vector direction;
  428.     local    vector    src;
  429.     
  430.     makevectors(self.v_angle);
  431.  
  432.     src = self.origin + v_forward*10;
  433.     src_z = self.absmin_z + self.size_z * 0.7;
  434.  
  435.     ClearMultiDamage ();
  436.     while (shotcount > 0)
  437.     {
  438.         direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
  439.  
  440.         traceline (src, src + direction*2048, FALSE, self);
  441.         if (trace_fraction != 1.0)
  442.             TraceAttack (4, direction);
  443.  
  444.         shotcount = shotcount - 1;
  445.     }
  446.     ApplyMultiDamage ();
  447. };
  448.  
  449. /*
  450. ================
  451. W_FireShotgun
  452. ================
  453. */
  454. void() W_FireShotgun =
  455. {
  456.     local vector dir;
  457.  
  458.     sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);    
  459.  
  460.     self.punchangle_x = -2;
  461.     
  462.     self.currentammo = self.ammo_shells = self.ammo_shells - 1;
  463.     dir = aim (self, 100000);
  464.     FireBullets (6, dir, '0.04 0.04 0');
  465. };
  466.  
  467.  
  468. /*
  469. ================
  470. W_FireSuperShotgun
  471. ================
  472. */
  473. void() W_FireSuperShotgun =
  474. {
  475.     local vector dir;
  476.  
  477.     if (self.currentammo == 1)
  478.     {
  479.         W_FireShotgun ();
  480.         return;
  481.     }
  482.         
  483.     sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);    
  484.  
  485.     self.punchangle_x = -4;
  486.     
  487.     self.currentammo = self.ammo_shells = self.ammo_shells - 2;
  488.     dir = aim (self, 100000);
  489.     FireBullets (14, dir, '0.14 0.08 0');
  490. };
  491.  
  492.  
  493. /*
  494. ================
  495. FireSniperBullet
  496. Used by sniper rifle firing (W_FireSniperRifle)
  497. ================
  498. */
  499. void(vector direction, float damage) FireSniperBullet =
  500. {
  501.     local    vector    src;
  502.  
  503.     makevectors(self.v_angle);
  504.  
  505.     src = self.origin + v_forward*10;
  506.     src_z = self.absmin_z + self.size_z * 0.7;
  507.  
  508.     ClearMultiDamage ();
  509.  
  510.     traceline (src, src + direction*2048, FALSE, self);
  511.     if (trace_fraction != 1.0)
  512.            TraceAttack (damage, direction);
  513.  
  514.     ApplyMultiDamage ();
  515. };
  516.  
  517.  
  518. /*
  519. =================================
  520. TeamFortress : W_FireSniperRifle
  521. =================================
  522. */
  523. void() W_FireSniperRifle =
  524. {
  525.     local vector dir;
  526.  
  527.     if (IS_NET_SERVER)
  528.         sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);    
  529.     else
  530.         sound (self ,CHAN_WEAPON, "weapons/sniper.wav", 1, ATTN_NORM);
  531.  
  532.     self.punchangle_x = -2;
  533.  
  534.     self.currentammo = self.ammo_shells = self.ammo_shells - 1;
  535.     dir = aim (self, 100000);
  536.     FireSniperBullet (dir,200);
  537. };
  538.  
  539. /*
  540. ===================================
  541. TeamFortress : W_FireAutoRifle
  542. ===================================
  543. */
  544. void() W_FireAutoRifle =
  545. {
  546.     local vector dir;
  547.  
  548.     if (IS_NET_SERVER)
  549.         sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);    
  550.     else
  551.         sound (self ,CHAN_WEAPON, "weapons/sniper.wav", 1, ATTN_NORM);
  552.  
  553.     self.punchangle_x = -2;
  554.  
  555.     self.currentammo = self.ammo_shells = self.ammo_shells - 1;
  556.     dir = aim (self, 100000);
  557.     FireSniperBullet (dir,4);
  558. };
  559.  
  560. /*
  561. ================
  562. TeamFortress : W_FireAssaultCannon
  563. ================
  564. */
  565. void() W_FireAssaultCannon =
  566. {
  567.     local vector dir;
  568.  
  569.     // Get a minigun sound effect
  570.     sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);    
  571.  
  572.     self.punchangle_x = -4;
  573.     
  574.     self.currentammo = self.ammo_shells = self.ammo_shells - 1;
  575.     dir = aim (self, 100000);
  576.     FireBullets (5, dir, '0.04 0.04 0');
  577. };
  578.  
  579. /*
  580. ==============================================================================
  581.  
  582. ROCKETS
  583.  
  584. ==============================================================================
  585. */
  586.  
  587. void()    s_explode1    =    [0,        s_explode2] {};
  588. void()    s_explode2    =    [1,        s_explode3] {};
  589. void()    s_explode3    =    [2,        s_explode4] {};
  590. void()    s_explode4    =    [3,        s_explode5] {};
  591. void()    s_explode5    =    [4,        s_explode6] {};
  592. void()    s_explode6    =    [5,        SUB_Remove] {};
  593.  
  594. void() BecomeExplosion =
  595. {
  596.     self.movetype = MOVETYPE_NONE;
  597.     self.velocity = '0 0 0';
  598.     self.touch = SUB_Null;
  599.     setmodel (self, "progs/s_explod.spr");
  600.     self.solid = SOLID_NOT;
  601.     s_explode1 ();
  602. };
  603.  
  604. void() T_MissileTouch =
  605. {
  606.     local float    damg;
  607.  
  608.     if (other == self.owner)
  609.         return;        // don't explode on owner
  610.  
  611.     if (pointcontents(self.origin) == CONTENT_SKY)
  612.     {
  613.         remove(self);
  614.         return;
  615.     }
  616.  
  617.     damg = 100 + random()*20;
  618.     
  619.     if (other.health)
  620.     {
  621.         if (other.classname == "monster_shambler")
  622.             damg = damg * 0.5;    // mostly immune
  623.         T_Damage (other, self, self.owner, damg );
  624.     }
  625.  
  626.     // don't do radius damage to the other, because all the damage
  627.     // was done in the impact
  628.     T_RadiusDamage (self, self.owner, 120, other);
  629.  
  630. //    sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
  631.     self.origin = self.origin - 8*normalize(self.velocity);
  632.  
  633.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  634.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  635.     WriteCoord (MSG_BROADCAST, self.origin_x);
  636.     WriteCoord (MSG_BROADCAST, self.origin_y);
  637.     WriteCoord (MSG_BROADCAST, self.origin_z);
  638.  
  639.     BecomeExplosion ();
  640. };
  641.  
  642.  
  643.  
  644. /*
  645. ================
  646. W_FireRocket
  647. ================
  648. */
  649. void() W_FireRocket =
  650. {
  651.     local    entity missile, mpuff;
  652.     
  653.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  654.     
  655.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  656.  
  657.     self.punchangle_x = -2;
  658.  
  659.     missile = spawn ();
  660.     missile.owner = self;
  661.     missile.movetype = MOVETYPE_FLYMISSILE;
  662.     missile.solid = SOLID_BBOX;
  663.         
  664.     // set missile speed    
  665.     makevectors (self.v_angle);
  666.     missile.velocity = aim(self, 1000);
  667.     missile.velocity = missile.velocity * 1000;
  668.     missile.angles = vectoangles(missile.velocity);
  669.     
  670.     missile.touch = T_MissileTouch;
  671.  
  672.     // Set ALTKILL
  673.     missile.tfstate = missile.tfstate | TFSTATE_ALTKILL;
  674.     missile.altkillweapon = AK_MISSILE;
  675.     
  676.     // set missile duration
  677.     missile.nextthink = time + 5;
  678.     missile.think = SUB_Remove;
  679.  
  680.     setmodel (missile, "progs/missile.mdl");
  681.     setsize (missile, '0 0 0', '0 0 0');        
  682.     setorigin (missile, self.origin + v_forward*8 + '0 0 16');
  683. };
  684.  
  685. /*
  686. ===============================================================================
  687.  
  688. LIGHTNING
  689.  
  690. ===============================================================================
  691. */
  692.  
  693. /*
  694. =================
  695. LightningDamage
  696. =================
  697. */
  698. void(vector p1, vector p2, entity from, float damage) LightningDamage =
  699. {
  700.     local entity        e1, e2;
  701.     local vector        f;
  702.     
  703.     f = p2 - p1;
  704.     normalize (f);
  705.     f_x = 0 - f_y;
  706.     f_y = f_x;
  707.     f_z = 0;
  708.     f = f*16;
  709.  
  710.     e1 = e2 = world;
  711.  
  712.     traceline (p1, p2, FALSE, self);
  713.     if (trace_ent.takedamage)
  714.     {
  715.         particle (trace_endpos, '0 0 100', 225, damage*4);
  716.         TF_T_Damage (trace_ent, from, from, damage, TF_TD_NOTTEAM);
  717.         if (self.classname == "player")
  718.         {
  719.             if (other.classname == "player")
  720.                 trace_ent.velocity_z = trace_ent.velocity_z + 400;
  721.         }
  722.     }
  723.     e1 = trace_ent;
  724.  
  725.     traceline (p1 + f, p2 + f, FALSE, self);
  726.     if (trace_ent != e1 && trace_ent.takedamage)
  727.     {
  728.         particle (trace_endpos, '0 0 100', 225, damage*4);
  729.         TF_T_Damage (trace_ent, from, from, damage, TF_TD_NOTTEAM);
  730.     }
  731.     e2 = trace_ent;
  732.  
  733.     traceline (p1 - f, p2 - f, FALSE, self);
  734.     if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
  735.     {
  736.         particle (trace_endpos, '0 0 100', 225, damage*4);
  737.         TF_T_Damage (trace_ent, from, from, damage, TF_TD_NOTTEAM);
  738.     }
  739. };
  740.  
  741.  
  742. void() W_FireLightning =
  743. {
  744.     local    vector        org;
  745.  
  746.     if (self.ammo_cells < 1)
  747.     {
  748.         self.weapon = W_BestWeapon ();
  749.         W_SetCurrentAmmo ();
  750.         return;
  751.     }
  752.  
  753. // explode if under water
  754.     if (self.waterlevel > 1)
  755.     {
  756.         T_RadiusDamage (self, self, 35*self.ammo_cells, world);
  757.         self.ammo_cells = 0;
  758.         W_SetCurrentAmmo ();
  759.         return;
  760.     }
  761.  
  762.     if (self.t_width < time)
  763.     {
  764.         sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
  765.         self.t_width = time + 0.6;
  766.     }
  767.     self.punchangle_x = -2;
  768.  
  769.     self.currentammo = self.ammo_cells = self.ammo_cells - 1;
  770.  
  771.     org = self.origin + '0 0 16';
  772.     
  773.     traceline (org, org + v_forward*600, TRUE, self);
  774.  
  775.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  776.     WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
  777.     WriteEntity (MSG_BROADCAST, self);
  778.     WriteCoord (MSG_BROADCAST, org_x);
  779.     WriteCoord (MSG_BROADCAST, org_y);
  780.     WriteCoord (MSG_BROADCAST, org_z);
  781.     WriteCoord (MSG_BROADCAST, trace_endpos_x);
  782.     WriteCoord (MSG_BROADCAST, trace_endpos_y);
  783.     WriteCoord (MSG_BROADCAST, trace_endpos_z);
  784.  
  785.     LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
  786. };
  787.  
  788.  
  789. //=============================================================================
  790.  
  791.  
  792. void() GrenadeExplode =
  793. {
  794.     T_RadiusDamage (self, self.owner, 120, world);
  795.  
  796.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  797.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  798.     WriteCoord (MSG_BROADCAST, self.origin_x);
  799.     WriteCoord (MSG_BROADCAST, self.origin_y);
  800.     WriteCoord (MSG_BROADCAST, self.origin_z);
  801.  
  802.     BecomeExplosion ();
  803. };
  804.  
  805. void() GrenadeTouch =
  806. {
  807.     if (other == self.owner)
  808.         return;        // don't explode on owner
  809.     if (other.takedamage == DAMAGE_AIM)
  810.     {
  811.         GrenadeExplode();
  812.         return;
  813.     }
  814.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);    // bounce sound
  815.     if (self.velocity == '0 0 0')
  816.         self.avelocity = '0 0 0';
  817. };
  818.  
  819. /*
  820. ================
  821. W_FireGrenade
  822. ================
  823. */
  824. void() W_FireGrenade =
  825. {
  826.     local    entity missile, mpuff;
  827.     
  828.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  829.  
  830.     sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  831.  
  832.     self.punchangle_x = -2;
  833.  
  834.     missile = spawn ();
  835.     missile.owner = self;
  836.     missile.movetype = MOVETYPE_BOUNCE;
  837.     missile.solid = SOLID_BBOX;
  838.  
  839.     // Set grenade type based on firing mode
  840.     if (self.weaponmode == GL_NORMAL)
  841.     {
  842.         missile.classname = "grenade";
  843.         missile.touch = GrenadeTouch;
  844.         missile.nextthink = time + 2.5;
  845.     }
  846.     if (self.weaponmode == GL_PIPEBOMB)
  847.     {
  848.         missile.classname = "pipebomb";
  849.         missile.touch = PipebombTouch;
  850.         missile.nextthink = time + (60 * 3);        // Remove pipebombs older than 3 minutes
  851.     }
  852.         
  853.     // set missile speed    
  854.     makevectors (self.v_angle);
  855.     if (self.v_angle_x)
  856.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  857.     else
  858.     {
  859.         missile.velocity = aim(self, 10000);
  860.         missile.velocity = missile.velocity * 600;
  861.         missile.velocity_z = 200;
  862.     }
  863.     missile.avelocity = '300 300 300';
  864.     missile.angles = vectoangles(missile.velocity);
  865.  
  866.     // Set ALTKILL
  867.     missile.tfstate = missile.tfstate | TFSTATE_ALTKILL;
  868.     missile.altkillweapon = AK_MISSILE;
  869.  
  870.     missile.think = GrenadeExplode;
  871.     setmodel (missile, "progs/grenade.mdl");
  872.     setsize (missile, '0 0 0', '0 0 0');        
  873.     setorigin (missile, self.origin);
  874. };
  875.  
  876. //=============================================================================
  877.  
  878. void() spike_touch;
  879. void() superspike_touch;
  880.  
  881.  
  882. /*
  883. ===============
  884. launch_spike
  885.  
  886. Used for both the player and the ogre
  887. ===============
  888. */
  889. void(vector org, vector dir, float Ak, float AkW) launch_spike =
  890. {
  891.     newmis = spawn ();
  892.     newmis.owner = self;
  893.     newmis.movetype = MOVETYPE_FLYMISSILE;
  894.     newmis.solid = SOLID_BBOX;
  895.  
  896.     newmis.angles = vectoangles(dir);
  897.  
  898.     // Alternative weapon
  899.     if (Ak)
  900.     {
  901.         newmis.tfstate = newmis.tfstate | TFSTATE_ALTKILL;
  902.         newmis.altkillweapon = AkW;
  903.     }
  904.     
  905.     newmis.touch = spike_touch;
  906.     newmis.classname = "spike";
  907.     newmis.think = SUB_Remove;
  908.     newmis.nextthink = time + 6;
  909.     setmodel (newmis, "progs/spike.mdl");
  910.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);        
  911.     setorigin (newmis, org);
  912.  
  913.     newmis.velocity = dir * 1000;
  914. };
  915.  
  916. void() W_FireSuperSpikes =
  917. {
  918.     local vector    dir;
  919.     local entity    old;
  920.     
  921.     sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
  922.     self.attack_finished = time + 0.2;
  923.     self.currentammo = self.ammo_nails = self.ammo_nails - 2;
  924.     dir = aim (self, 1000);
  925.     launch_spike (self.origin + '0 0 16', dir,0 ,0);
  926.     newmis.touch = superspike_touch;
  927.     setmodel (newmis, "progs/s_spike.mdl");
  928.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);        
  929.     self.punchangle_x = -2;
  930. };
  931.  
  932. void(float ox) W_FireSpikes =
  933. {
  934.     local vector    dir;
  935.     local entity    old;
  936.     
  937.     makevectors (self.v_angle);
  938.     
  939.     if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
  940.     {
  941.         W_FireSuperSpikes ();
  942.         return;
  943.     }
  944.  
  945.     if (self.ammo_nails < 1)
  946.     {
  947.         self.weapon = W_BestWeapon ();
  948.         W_SetCurrentAmmo ();
  949.         return;
  950.     }
  951.  
  952.     sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
  953.     self.attack_finished = time + 0.2;
  954.     self.currentammo = self.ammo_nails = self.ammo_nails - 1;
  955.     dir = aim (self, 1000);
  956.     launch_spike (self.origin + '0 0 16' + v_right*ox, dir, 0, 0);
  957.  
  958.     self.punchangle_x = -2;
  959. };
  960.  
  961.  
  962.  
  963. .float hit_z;
  964. void() spike_touch =
  965. {
  966. local float rand;
  967.     if (other == self.owner)
  968.         return;
  969.  
  970.     if (other.solid == SOLID_TRIGGER)
  971.         return;    // trigger field, do nothing
  972.  
  973.     if (pointcontents(self.origin) == CONTENT_SKY)
  974.     {
  975.         remove(self);
  976.         return;
  977.     }
  978.     
  979. // hit something that bleeds
  980.     if (other.takedamage)
  981.     {
  982.         spawn_touchblood (9);
  983.         TF_T_Damage (other, self, self.owner, 9, TF_TD_NOTTEAM);
  984.     }
  985.     else
  986.     {
  987.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  988.         
  989.         if (self.classname == "wizspike")
  990.             WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
  991.         else if (self.classname == "knightspike")
  992.             WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
  993.         else
  994.             WriteByte (MSG_BROADCAST, TE_SPIKE);
  995.         WriteCoord (MSG_BROADCAST, self.origin_x);
  996.         WriteCoord (MSG_BROADCAST, self.origin_y);
  997.         WriteCoord (MSG_BROADCAST, self.origin_z);
  998.     }
  999.  
  1000.     remove(self);
  1001.  
  1002. };
  1003.  
  1004. void() superspike_touch =
  1005. {
  1006. local float rand;
  1007.     if (other == self.owner)
  1008.         return;
  1009.  
  1010.     if (other.solid == SOLID_TRIGGER)
  1011.         return;    // trigger field, do nothing
  1012.  
  1013.     if (pointcontents(self.origin) == CONTENT_SKY)
  1014.     {
  1015.         remove(self);
  1016.         return;
  1017.     }
  1018.     
  1019. // hit something that bleeds
  1020.     if (other.takedamage)
  1021.     {
  1022.         spawn_touchblood (18);
  1023.         TF_T_Damage (other, self, self.owner, 18, TF_TD_NOTTEAM);
  1024.     }
  1025.     else
  1026.     {
  1027.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1028.         WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
  1029.         WriteCoord (MSG_BROADCAST, self.origin_x);
  1030.         WriteCoord (MSG_BROADCAST, self.origin_y);
  1031.         WriteCoord (MSG_BROADCAST, self.origin_z);
  1032.     }
  1033.  
  1034.     remove(self);
  1035.  
  1036. };
  1037.  
  1038. /*
  1039. ===============================================================================
  1040.  
  1041. PLAYER WEAPON USE
  1042.  
  1043. ===============================================================================
  1044. */
  1045.  
  1046. void() W_SetCurrentAmmo =
  1047. {
  1048.     player_run ();        // get out of any weapon firing states
  1049.  
  1050.     self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
  1051.     
  1052.     if (self.weapon == IT_AXE)
  1053.     {
  1054.         self.currentammo = 0;
  1055.         self.weaponmodel = "progs/v_axe.mdl";
  1056.         self.weaponframe = 0;
  1057.     }
  1058.     else if (self.weapon == IT_SHOTGUN)
  1059.     {
  1060.         self.currentammo = self.ammo_shells;
  1061.         if (!(self.tfstate & TFSTATE_RELOADING))
  1062.         {
  1063.             self.weaponmodel = "progs/v_shot.mdl";
  1064.             self.weaponframe = 0;
  1065.         }
  1066.         self.items = self.items | IT_SHELLS;
  1067.     }
  1068.     else if (self.weapon == IT_SUPER_SHOTGUN)
  1069.     {
  1070.         self.currentammo = self.ammo_shells;
  1071.         if (!(self.tfstate & TFSTATE_RELOADING))
  1072.         {
  1073.             self.weaponmodel = "progs/v_shot2.mdl";
  1074.             self.weaponframe = 0;
  1075.         }
  1076.         self.items = self.items | IT_SHELLS;
  1077.     }
  1078.     else if (self.weapon == IT_NAILGUN)
  1079.     {
  1080.         self.currentammo = self.ammo_nails;
  1081.         if (!(self.tfstate & TFSTATE_RELOADING))
  1082.         {
  1083.             self.weaponmodel = "progs/v_nail.mdl";
  1084.             self.weaponframe = 0;
  1085.         }
  1086.         self.items = self.items | IT_NAILS;
  1087.     }
  1088.     else if (self.weapon == IT_SUPER_NAILGUN)
  1089.     {
  1090.         self.currentammo = self.ammo_nails;
  1091.         if (!(self.tfstate & TFSTATE_RELOADING))
  1092.         {
  1093.             self.weaponmodel = "progs/v_nail2.mdl";
  1094.             self.weaponframe = 0;
  1095.         }
  1096.         self.items = self.items | IT_NAILS;
  1097.     }
  1098.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  1099.     {
  1100.         self.currentammo = self.ammo_rockets;
  1101.         if (!(self.tfstate & TFSTATE_RELOADING))
  1102.         {
  1103.             self.weaponmodel = "progs/v_rock.mdl";
  1104.             self.weaponframe = 0;
  1105.         }
  1106.         if (self.weaponmode == GL_NORMAL)
  1107.             sprint(self, "Normal grenade mode\n");
  1108.         if (self.weaponmode == GL_PIPEBOMB)
  1109.             sprint(self, "Pipebomb mode\n");
  1110.         self.items = self.items | IT_ROCKETS;
  1111.     }
  1112.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  1113.     {
  1114.         self.currentammo = self.ammo_rockets;
  1115.         if (!(self.tfstate & TFSTATE_RELOADING))
  1116.         {
  1117.             self.weaponmodel = "progs/v_rock2.mdl";
  1118.             self.weaponframe = 0;
  1119.         }
  1120.         self.items = self.items | IT_ROCKETS;
  1121.     }
  1122.     else if (self.weapon == IT_LIGHTNING)
  1123.     {
  1124.         self.currentammo = self.ammo_cells;
  1125.         if (!(self.tfstate & TFSTATE_RELOADING))
  1126.         {
  1127.             self.weaponmodel = "progs/v_light.mdl";
  1128.             self.weaponframe = 0;
  1129.         }
  1130.         self.items = self.items | IT_CELLS;
  1131.     }
  1132.     else if (self.weapon == IT_EXTRA_WEAPON)
  1133.     {
  1134.            if (self.secondary_weapon == NIT_SNIPER_RIFLE)
  1135.           {
  1136.             self.currentammo = self.ammo_shells;
  1137.             if (!(self.tfstate & TFSTATE_RELOADING))
  1138.             {
  1139.                 self.weaponmodel = "progs/v_shot.mdl";
  1140.                  self.weaponframe = 0;
  1141.             }
  1142.             self.items = self.items | IT_SHELLS;
  1143.  
  1144.              sprint(self,"Sniper rifle ready\n");
  1145.         }
  1146.         else if (self.secondary_weapon == NIT_AUTO_RIFLE)
  1147.          {
  1148.               self.currentammo = self.ammo_shells;
  1149.             if (!(self.tfstate & TFSTATE_RELOADING))
  1150.             {
  1151.                 self.weaponmodel = "progs/v_shot.mdl";
  1152.                 self.weaponframe = 0;
  1153.             }
  1154.             self.items = self.items | IT_SHELLS;
  1155.              sprint(self,"Rifle on fully auto\n");
  1156.         }
  1157.         else if (self.secondary_weapon == NIT_ASSAULT_CANNON)
  1158.          {
  1159.               self.currentammo = self.ammo_shells;
  1160.             if ((!(self.tfstate & TFSTATE_RELOADING)) && (self.heat == 0))
  1161.             {
  1162.                 self.weaponmodel = "progs/v_nail2.mdl";
  1163.                 self.weaponframe = 0;
  1164.             }
  1165.             self.items = self.items | IT_SHELLS;
  1166.         }
  1167.         else if (self.secondary_weapon == NIT_MEDIKIT)
  1168.         {
  1169.             self.currentammo = 0;
  1170.             self.weaponmodel = "progs/v_axe.mdl";
  1171.             self.weaponframe = 0;
  1172.             
  1173.             sprint(self, "Medikit readied\n");
  1174.            }
  1175.         else if (self.secondary_weapon == NIT_BIOWEAPON)
  1176.         {
  1177.             self.currentammo = 0;
  1178.             self.weaponmodel = "progs/v_axe.mdl";
  1179.             self.weaponframe = 0;
  1180.  
  1181.             sprint(self, "BioWeapon readied\n");
  1182.         }
  1183.     }
  1184.     else
  1185.     {
  1186.         self.currentammo = 0;
  1187.         self.weaponmodel = "";
  1188.         self.weaponframe = 0;
  1189.     }
  1190. };
  1191.  
  1192. float() W_BestWeapon =
  1193. {
  1194.     local    float    it;
  1195.     
  1196.     it = self.items;
  1197.  
  1198.     if(self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
  1199.         return IT_LIGHTNING;
  1200.     else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
  1201.         return IT_SUPER_NAILGUN;
  1202.     else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
  1203.         return IT_SUPER_SHOTGUN;
  1204.     else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
  1205.         return IT_NAILGUN;
  1206.     else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) )
  1207.         return IT_SHOTGUN;
  1208.         
  1209. /*
  1210.     if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
  1211.         return IT_ROCKET_LAUNCHER;
  1212.     else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
  1213.         return IT_GRENADE_LAUNCHER;
  1214.  
  1215. */
  1216.  
  1217.     if (self.playerclass == PC_MEDIC)
  1218.     {
  1219.         self.secondary_weapon = NIT_BIOWEAPON;
  1220.         return IT_EXTRA_WEAPON;
  1221.     }
  1222.  
  1223.     return IT_AXE;
  1224. };
  1225.  
  1226. float() W_CheckNoAmmo =
  1227. {
  1228.     if (self.currentammo > 0)
  1229.         return TRUE;
  1230.  
  1231.     if (self.weapon == IT_AXE)
  1232.         return TRUE;
  1233.  
  1234.     if (self.weapon == IT_EXTRA_WEAPON)
  1235.     {
  1236.         if (self.secondary_weapon == NIT_MEDIKIT)
  1237.             return TRUE;
  1238.  
  1239.         if (self.secondary_weapon == NIT_BIOWEAPON)
  1240.             return TRUE;
  1241.     }
  1242.     
  1243.     self.weapon = W_BestWeapon ();
  1244.  
  1245.     W_SetCurrentAmmo ();
  1246.     
  1247. // drop the weapon down
  1248.     return FALSE;
  1249. };
  1250.  
  1251. /*====================
  1252. W_Reload
  1253. Is called when weapon has finished reloading
  1254. ====================*/
  1255. void() W_Reload_shotgun =
  1256. {
  1257.     self.owner.tfstate = self.owner.tfstate - (self.owner.tfstate & TFSTATE_RELOADING);
  1258.     self.owner.weaponmodel = "progs/v_shot.mdl";
  1259.     sprint(self.owner, "finished reloading\n");
  1260.     remove(self);
  1261. };
  1262.  
  1263. void() W_Reload_super_shotgun =
  1264. {
  1265.     self.owner.tfstate = self.owner.tfstate - (self.owner.tfstate & TFSTATE_RELOADING);
  1266.     self.owner.weaponmodel = "progs/v_shot2.mdl";
  1267.     sprint(self.owner, "finished reloading\n");
  1268.     remove(self);
  1269. };
  1270.  
  1271. void() W_Reload_grenade_launcher =
  1272. {
  1273.     self.owner.tfstate = self.owner.tfstate - (self.owner.tfstate & TFSTATE_RELOADING);
  1274.     self.owner.weaponmodel = "progs/v_rock.mdl";
  1275.     sprint(self.owner, "finished reloading\n");
  1276.     remove(self);
  1277. };
  1278.  
  1279. void() W_Reload_rocket_launcher =
  1280. {
  1281.     self.owner.tfstate = self.owner.tfstate - (self.owner.tfstate & TFSTATE_RELOADING);
  1282.     self.owner.weaponmodel = "progs/v_rock2.mdl";
  1283.     sprint(self.owner, "finished reloading\n");
  1284.     remove(self);
  1285. };
  1286.  
  1287. void() W_Cool_assault_cannon =
  1288. {
  1289.     self.owner.heat = 0;
  1290.     if (self.owner.weapon == IT_EXTRA_WEAPON && self.owner.secondary_weapon == NIT_ASSAULT_CANNON)
  1291.         self.owner.weaponmodel = "progs/v_nail2.mdl";
  1292.     sprint(self.owner, "Assault cannon cooled.\n");
  1293.     remove(self);
  1294. };
  1295.  
  1296. /*
  1297. ============
  1298. W_Attack
  1299.  
  1300. An attack impulse can be triggered now
  1301. ============
  1302. */
  1303. void()    player_axe1;
  1304. void()    player_axeb1;
  1305. void()    player_axec1;
  1306. void()    player_axed1;
  1307. void()    player_shot1;
  1308. void()    player_nail1;
  1309. void()    player_light1;
  1310. void()    player_rocket1;
  1311.  
  1312. void()    player_autorifle1;
  1313. void()  player_assaultcannon1;
  1314. void()    player_medikit1;
  1315. void()    player_medikitb1;
  1316. void()    player_medikitc1;
  1317. void()    player_medikitd1;
  1318. void()    player_bioweapon1;
  1319. void()    player_bioweaponb1;
  1320. void()    player_bioweaponc1;
  1321. void()    player_bioweapond1;
  1322.  
  1323. void() W_Attack =
  1324. {
  1325.     local    float    r;
  1326.     local   entity  tWeapon;
  1327.  
  1328.     if (!W_CheckNoAmmo ())
  1329.         return;
  1330.  
  1331.     if (self.tfstate & TFSTATE_RELOADING)
  1332.         return;
  1333.  
  1334.     makevectors    (self.v_angle);            // calculate forward angle for velocity
  1335.     self.show_hostile = time + 1;    // wake monsters up
  1336.  
  1337.     if (self.weapon == IT_AXE)
  1338.     {
  1339.         sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
  1340.         r = random();
  1341.         if (r < 0.25)
  1342.             player_axe1 ();
  1343.         else if (r<0.5)
  1344.             player_axeb1 ();
  1345.         else if (r<0.75)
  1346.             player_axec1 ();
  1347.         else
  1348.             player_axed1 ();
  1349.         self.attack_finished = time + 0.5;
  1350.     }
  1351.     else if (self.weapon == IT_SHOTGUN)
  1352.     {
  1353.         player_shot1 ();
  1354.         W_FireShotgun ();
  1355.         if (self.reload_shotgun >= RE_SHOTGUN)
  1356.         {
  1357.            self.attack_finished = time + 0.4;
  1358.            self.reload_shotgun = 0;
  1359.  
  1360.            sprint(self, "reloading...\n");
  1361.            self.tfstate = (self.tfstate | TFSTATE_RELOADING);
  1362.            tWeapon = spawn();
  1363.            tWeapon.owner = self;
  1364.            tWeapon.classname = "timer";
  1365.            tWeapon.nextthink = time + RE_SHOTGUN_TIME;
  1366.            tWeapon.think = W_Reload_shotgun;
  1367.  
  1368.            self.weaponmodel = "";
  1369.            self.weaponframe = 0;
  1370.         }
  1371.         else
  1372.         {
  1373.             self.attack_finished = time + 0.5;
  1374.             self.reload_shotgun = self.reload_shotgun + 1;
  1375.         }
  1376.     }
  1377.     else if (self.weapon == IT_SUPER_SHOTGUN)
  1378.     {
  1379.         player_shot1 ();
  1380.         W_FireSuperShotgun ();
  1381.         if (self.reload_super_shotgun >= RE_SUPER_SHOTGUN)
  1382.         {
  1383.             self.attack_finished = time + 0.7;
  1384.             self.reload_super_shotgun = 0;
  1385.  
  1386.               sprint(self, "reloading...\n");
  1387.             self.tfstate = (self.tfstate | TFSTATE_RELOADING);
  1388.             tWeapon = spawn();
  1389.             tWeapon.owner = self;
  1390.              tWeapon.classname = "timer";
  1391.             tWeapon.nextthink = time + RE_SUPER_SHOTGUN_TIME;
  1392.              tWeapon.think = W_Reload_super_shotgun;
  1393.  
  1394.              self.weaponmodel = "";
  1395.              self.weaponframe = 0;
  1396.           }
  1397.           else
  1398.           {
  1399.             self.attack_finished = time + 0.7;
  1400.              self.reload_super_shotgun = self.reload_super_shotgun + 1;
  1401.           }
  1402.     }
  1403.     else if (self.weapon == IT_NAILGUN)
  1404.     {
  1405.         player_nail1 ();
  1406.     }
  1407.     else if (self.weapon == IT_SUPER_NAILGUN)
  1408.     {
  1409.         player_nail1 ();
  1410.     }
  1411.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  1412.     {
  1413.         player_rocket1();
  1414.         W_FireGrenade();
  1415.         if (self.reload_grenade_launcher >= RE_GRENADE_LAUNCHER)
  1416.         {
  1417.             self.attack_finished = time + 0.6;
  1418.               self.reload_grenade_launcher = 0;
  1419.  
  1420.                 sprint(self, "reloading...\n");
  1421.             self.tfstate = (self.tfstate | TFSTATE_RELOADING);
  1422.               tWeapon = spawn();
  1423.               tWeapon.owner = self;
  1424.              tWeapon.classname = "timer";
  1425.               tWeapon.nextthink = time + RE_GRENADE_LAUNCHER_TIME;
  1426.              tWeapon.think = W_Reload_grenade_launcher;
  1427.  
  1428.              self.weaponmodel = "";
  1429.              self.weaponframe = 0;
  1430.           }
  1431.           else
  1432.           {
  1433.             self.attack_finished = time + 0.6;
  1434.              self.reload_grenade_launcher = self.reload_grenade_launcher + 1;
  1435.           }
  1436.     }
  1437.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  1438.     {
  1439.         player_rocket1();
  1440.         W_FireRocket();
  1441.         if (self.reload_rocket_launcher >= RE_ROCKET_LAUNCHER)
  1442.           {
  1443.             self.attack_finished = time + 0.8;
  1444.             self.reload_rocket_launcher = 0;
  1445.  
  1446.               sprint(self, "reloading...\n");
  1447.             self.tfstate = (self.tfstate | TFSTATE_RELOADING);
  1448.              tWeapon = spawn();
  1449.              tWeapon.owner = self;
  1450.              tWeapon.classname = "timer";
  1451.              tWeapon.nextthink = time + RE_ROCKET_LAUNCHER_TIME;
  1452.              tWeapon.think = W_Reload_rocket_launcher;
  1453.  
  1454.              self.weaponmodel = "";
  1455.              self.weaponframe = 0;
  1456.           }
  1457.           else
  1458.           {
  1459.             self.attack_finished = time + 0.8;
  1460.              self.reload_rocket_launcher = self.reload_rocket_launcher + 1;
  1461.           }
  1462.     }
  1463.     else if (self.weapon == IT_LIGHTNING)
  1464.     {
  1465.         player_light1();
  1466.         self.attack_finished = time + 0.1;
  1467.         sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
  1468.     }
  1469.     else if (self.weapon == IT_EXTRA_WEAPON)
  1470.     {
  1471.         if (self.secondary_weapon == NIT_SNIPER_RIFLE)
  1472.         {
  1473.             if (vlen(self.velocity) > NIT_SNIPER_RIFLE_MAX_MOVE)
  1474.                 return;
  1475.  
  1476.                // player_sniper1 (); (TBD?)
  1477.               player_shot1();
  1478.               W_FireSniperRifle();
  1479.              self.attack_finished = time + 3.0;
  1480.           }
  1481.           else if (self.secondary_weapon == NIT_AUTO_RIFLE)
  1482.           {
  1483.             // player_sniper1 (); (TBD?)
  1484.               player_autorifle1();
  1485.              W_FireAutoRifle();
  1486.              self.attack_finished = time + 0.1;
  1487.           }
  1488.           else if (self.secondary_weapon == NIT_ASSAULT_CANNON)
  1489.           {
  1490.             // TBD: Do the 1 second "warm up cannon" noise, and
  1491.             // then let them fire.
  1492.  
  1493.             // Need 10 cells to power up the Assault Cannon
  1494.             if (self.heat > 0)
  1495.             {
  1496.                 sprint(self, "Assault cannon is still cooling...");
  1497.                 return;
  1498.             }
  1499.             if (self.ammo_cells < 10)
  1500.                 sprint(self, "Insufficient cells to power up the Assault Cannon.\n");
  1501.             else
  1502.             {
  1503.                 self.ammo_cells = self.ammo_cells - 10;
  1504.  
  1505.                 // Can't move while firing the Assault Cannon :)
  1506.                 stuffcmd(self,"cl_backspeed 0\n");
  1507.                 stuffcmd(self,"cl_forwardspeed 0\n");
  1508.                 stuffcmd(self,"cl_sidespeed 0\n");
  1509.                   player_assaultcannon1();
  1510.             }
  1511.           }
  1512.         else if (self.secondary_weapon == NIT_MEDIKIT)
  1513.         {
  1514.             sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
  1515.             r = random();
  1516.             if (r < 0.25)
  1517.                 player_medikit1 ();
  1518.             else if (r<0.5)
  1519.                 player_medikitb1 ();
  1520.             else if (r<0.75)
  1521.                 player_medikitc1 ();
  1522.             else
  1523.                 player_medikitd1 ();
  1524.             self.attack_finished = time + 0.5;
  1525.  
  1526.         }
  1527.         else if (self.secondary_weapon == NIT_BIOWEAPON)
  1528.         {
  1529.             sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
  1530.             r = random();
  1531.             if (r < 0.25)
  1532.                 player_bioweapon1 ();
  1533.             else if (r<0.5)
  1534.                 player_bioweaponb1 ();
  1535.             else if (r<0.75)
  1536.                 player_bioweaponc1 ();
  1537.             else
  1538.                 player_bioweapond1 ();
  1539.             self.attack_finished = time + 0.5;
  1540.         }
  1541.     }
  1542. };
  1543.  
  1544. /*
  1545. ============
  1546. W_ChangeWeapon
  1547.  
  1548. ============
  1549. */
  1550. void() W_ChangeWeapon =
  1551. {
  1552.     local    float    it, am, fl;
  1553.     
  1554.     if (self.tfstate & TFSTATE_RELOADING)
  1555.            return;
  1556.  
  1557.     it = self.items;
  1558.     am = 0;
  1559.     
  1560.     if (self.impulse == 1)
  1561.     {
  1562.         // do they have the axe?
  1563.         if (!(self.items & IT_AXE) && !(self.items & NIT_BIOWEAPON))
  1564.         {
  1565.             // if not, they must have either BioWeapon or Medikit
  1566.             if (self.weapon == IT_EXTRA_WEAPON && self.secondary_weapon == NIT_BIOWEAPON)
  1567.             {
  1568.                 self.secondary_weapon = NIT_MEDIKIT;
  1569.             }
  1570.             else
  1571.             {
  1572.                 self.secondary_weapon = NIT_BIOWEAPON;
  1573.                 self.weapon = IT_EXTRA_WEAPON;
  1574.             }
  1575.         }
  1576.         else
  1577.         {
  1578.             if (self.items & IT_AXE)
  1579.             {
  1580.                 self.weapon = IT_AXE;
  1581.             }
  1582.             else
  1583.             {
  1584.                 self.weapon = 0;
  1585.             }
  1586.         }
  1587.  
  1588.         W_SetCurrentAmmo ();
  1589.         return;
  1590.     }
  1591.     else if (self.impulse == 2)
  1592.     {
  1593.         fl = IT_SHOTGUN;
  1594.         if (self.ammo_shells < 1)
  1595.             am = 1;
  1596.     }
  1597.     else if (self.impulse == 3)
  1598.     {
  1599.         fl = IT_SUPER_SHOTGUN;
  1600.         if (self.ammo_shells < 2)
  1601.             am = 1;
  1602.     }        
  1603.     else if (self.impulse == 4)
  1604.     {
  1605.         fl = IT_NAILGUN;
  1606.         if (self.ammo_nails < 1)
  1607.             am = 1;
  1608.     }
  1609.     else if (self.impulse == 5)
  1610.     {
  1611.         fl = IT_SUPER_NAILGUN;
  1612.         if (self.ammo_nails < 2)
  1613.             am = 1;
  1614.     }
  1615.     else if (self.impulse == 6)
  1616.     {
  1617.         fl = IT_GRENADE_LAUNCHER;
  1618.         if (self.ammo_rockets < 1)
  1619.             am = 1;
  1620.         if (self.weaponmode == GL_PIPEBOMB)
  1621.             self.weaponmode = GL_NORMAL;
  1622.         else if (self.weaponmode == GL_NORMAL)
  1623.             self.weaponmode = GL_PIPEBOMB;
  1624.     }
  1625.     else if (self.impulse == 7)
  1626.     {
  1627.         fl = IT_ROCKET_LAUNCHER;
  1628.         if (self.ammo_rockets < 1)
  1629.             am = 1;
  1630.     }
  1631.     else if (self.impulse == 8)
  1632.     {
  1633.         fl = IT_LIGHTNING;
  1634.         if (self.ammo_cells < 1)
  1635.             am = 1;
  1636.     }
  1637.  
  1638.     self.impulse = 0;
  1639.     
  1640.     if (!(self.items & fl))
  1641.     {    // don't have the weapon or the ammo
  1642.         sprint (self, "no weapon.\n");
  1643.         return;
  1644.     }
  1645.     
  1646.     if (am)
  1647.     {    // don't have the ammo
  1648.         sprint (self, "not enough ammo.\n");
  1649.         return;
  1650.     }
  1651.  
  1652. //
  1653. // set weapon, set ammo
  1654. //
  1655.     self.weapon = fl;        
  1656.     self.secondary_weapon = 0;
  1657.     W_SetCurrentAmmo ();
  1658. };
  1659.  
  1660. /*
  1661. ============
  1662. CheatCommand
  1663. ============
  1664. */
  1665. void() CheatCommand =
  1666. {
  1667.     if (deathmatch || coop)
  1668.         return;
  1669.  
  1670.     if (self.tfstate & TFSTATE_RELOADING)
  1671.            return;
  1672.  
  1673.     self.ammo_rockets = 100;
  1674.     self.ammo_nails = 200;
  1675.     self.ammo_shells = 100;
  1676.     self.items = self.items | 
  1677.         IT_AXE |
  1678.         IT_SHOTGUN |
  1679.         IT_SUPER_SHOTGUN |
  1680.         IT_NAILGUN |
  1681.         IT_SUPER_NAILGUN |
  1682.         IT_GRENADE_LAUNCHER |
  1683.         IT_ROCKET_LAUNCHER |
  1684.         IT_KEY1 | IT_KEY2;
  1685.  
  1686.     self.ammo_cells = 200;
  1687.     self.items = self.items | IT_LIGHTNING;
  1688.  
  1689.     self.impulse = 0;
  1690.  
  1691.     self.items = self.items | IT_EXTRA_WEAPON;
  1692.     self.weapon = IT_EXTRA_WEAPON;
  1693.     self.secondary_items = self.secondary_items | NIT_SNIPER_RIFLE | NIT_AUTO_RIFLE | NIT_ASSAULT_CANNON;
  1694.     self.secondary_weapon = NIT_SNIPER_RIFLE;
  1695.  
  1696.     W_SetCurrentAmmo ();
  1697. };
  1698.  
  1699. /*
  1700. ============
  1701. CycleWeaponCommand
  1702.  
  1703. Go to the next weapon with ammo
  1704. ============
  1705. */
  1706. void() CycleWeaponCommand =
  1707. {
  1708.     local    float    it, am;
  1709.     
  1710.     if (self.tfstate & TFSTATE_RELOADING)
  1711.           return;
  1712.  
  1713.     it = self.items;
  1714.     self.impulse = 0;
  1715.     
  1716.     while (1)
  1717.     {
  1718.         am = 0;
  1719.  
  1720.         if (self.weapon == IT_AXE)
  1721.         {
  1722.             self.weapon = IT_SHOTGUN;
  1723.             if (self.ammo_shells < 1)
  1724.                 am = 1;
  1725.         }
  1726.         else if (self.weapon == IT_SHOTGUN)
  1727.         {
  1728.             self.weapon = IT_SUPER_SHOTGUN;
  1729.             if (self.ammo_shells < 2)
  1730.                 am = 1;
  1731.         }        
  1732.         else if (self.weapon == IT_SUPER_SHOTGUN)
  1733.         {
  1734.             self.weapon = IT_NAILGUN;
  1735.             if (self.ammo_nails < 1)
  1736.                 am = 1;
  1737.         }
  1738.         else if (self.weapon == IT_NAILGUN)
  1739.         {
  1740.             self.weapon = IT_SUPER_NAILGUN;
  1741.             if (self.ammo_nails < 2)
  1742.                 am = 1;
  1743.         }
  1744.         else if (self.weapon == IT_SUPER_NAILGUN)
  1745.         {
  1746.             self.weapon = IT_GRENADE_LAUNCHER;
  1747.             self.weaponmode = GL_NORMAL;
  1748.             if (self.ammo_rockets < 1)
  1749.                 am = 1;
  1750.         }
  1751.         else if (self.weapon == IT_GRENADE_LAUNCHER && self.weaponmode == GL_NORMAL)
  1752.         {
  1753.             self.weapon = IT_GRENADE_LAUNCHER;
  1754.             self.weaponmode = GL_PIPEBOMB;
  1755.             if (self.ammo_rockets < 1)
  1756.                 am = 1;
  1757.         }
  1758.         else if (self.weapon == IT_GRENADE_LAUNCHER && self.weaponmode == GL_PIPEBOMB)
  1759.         {
  1760.             self.weapon = IT_ROCKET_LAUNCHER;
  1761.             if (self.ammo_rockets < 1)
  1762.                 am = 1;
  1763.         }
  1764.         else if (self.weapon == IT_ROCKET_LAUNCHER)
  1765.         {
  1766.             self.weapon = IT_LIGHTNING;
  1767.             if (self.ammo_cells < 1)
  1768.                 am = 1;
  1769.         }
  1770.         else if (self.weapon == IT_LIGHTNING)
  1771.         {
  1772.             self.weapon = IT_EXTRA_WEAPON;
  1773.              self.secondary_weapon = NIT_SNIPER_RIFLE;
  1774.              if (self.ammo_shells < 1)
  1775.                  am = 1;
  1776.           }
  1777.           else if (self.weapon == IT_EXTRA_WEAPON)
  1778.           {
  1779.               if (self.secondary_weapon == NIT_SNIPER_RIFLE)
  1780.              {
  1781.                  self.secondary_weapon = NIT_AUTO_RIFLE;
  1782.                 if (self.ammo_shells < 1)
  1783.                     am = 1;
  1784.              }
  1785.              else if (self.secondary_weapon == NIT_AUTO_RIFLE)
  1786.              {
  1787.                  self.secondary_weapon = NIT_ASSAULT_CANNON;
  1788.                 if (self.ammo_cells < 10)
  1789.                     am = 1;
  1790.                 if (self.ammo_shells < 1)
  1791.                     am = 1;
  1792.                 if (self.heat > 0)
  1793.                     am = 1;
  1794.              }
  1795.              else if (self.secondary_weapon == NIT_ASSAULT_CANNON)
  1796.              {
  1797.                  self.secondary_weapon = NIT_BIOWEAPON;
  1798.              }
  1799.             else if (self.secondary_weapon == NIT_BIOWEAPON)
  1800.             {
  1801.                 self.secondary_weapon = NIT_MEDIKIT;
  1802.             }
  1803.             else if (self.secondary_weapon == NIT_MEDIKIT)
  1804.             {
  1805.                 self.weapon = IT_AXE;
  1806.                 self.secondary_weapon = 0;
  1807.             }
  1808.           }
  1809.  
  1810.         // check if player actually has the weapon
  1811.           // if not, loop again
  1812.         if ((self.items & self.weapon) && (am == 0))
  1813.         {
  1814.               if (self.weapon == IT_EXTRA_WEAPON)
  1815.             {
  1816.                 if (self.secondary_items & self.secondary_weapon)
  1817.                 {
  1818.                     W_SetCurrentAmmo ();
  1819.                     return;
  1820.                 }
  1821.             }
  1822.             else
  1823.             {
  1824.                 W_SetCurrentAmmo ();
  1825.                 return;
  1826.             }
  1827.         }
  1828.     }
  1829. };
  1830.  
  1831. /*
  1832. ============
  1833. ServerflagsCommand
  1834.  
  1835. Just for development
  1836. ============
  1837. */
  1838. void() ServerflagsCommand =
  1839. {
  1840.     serverflags = serverflags * 2 + 1;
  1841. };
  1842.  
  1843. void() QuadCheat =
  1844. {
  1845.     if (deathmatch || coop)
  1846.         return;
  1847.     self.super_time = 1;
  1848.     self.super_damage_finished = time + 30;
  1849.     self.items = self.items | IT_QUAD;
  1850.     dprint ("quad cheat\n");
  1851. };
  1852.  
  1853. /*
  1854. ============
  1855. ImpulseCommands
  1856.  
  1857. ============
  1858. */
  1859. void() ImpulseCommands =
  1860. {
  1861.     /*=====================
  1862.     These Impulse commands rely on the use of self.last_impulse. Since they use 
  1863.     self.impulse for their own purposes, they _must_ be placed before the other 
  1864.     self.impulse tests, and they _must_ set self.impulse = 0 when they're done. 
  1865.     =====================*/
  1866.     // TeamFortress Detpack
  1867.     if (self.last_impulse == TF_DETPACK && self.impulse)
  1868.         TeamFortress_SetDetpack(self.impulse);
  1869.     // TeamFortress Scan
  1870.     if (self.last_impulse == TF_SCAN && self.impulse)
  1871.         TeamFortress_Scan(self.impulse);
  1872.     // TeamFortress Help
  1873.     if (self.last_impulse == TF_HELP && self.impulse)
  1874.         TeamFortress_Help(self.impulse);
  1875.     // TeamFortress Toggleable Game Setting
  1876.     if (self.last_impulse == TF_TOGGLE && self.impulse)
  1877.         TeamFortress_Toggle(self.impulse);
  1878.     // TeamFortress Multiskin Set Skin
  1879.     if (self.last_impulse == TF_MULTISKIN && self.impulse)
  1880.         TeamFortress_Multiskin(self.impulse);
  1881.     // TeamFortress Team Functions
  1882.     if (self.last_impulse == TF_TEAM && self.impulse)
  1883.         TeamFortress_Team(self.impulse);
  1884.  
  1885.     /*=====================
  1886.     The rest of these Impulse Commands don't use self.last_impulse. They _must_
  1887.     be placed _after_ the Impulse Commands that do require self.last_impulse 
  1888.     =====================*/
  1889.     // The sniper rifle replaces the normal shotgun
  1890.     if (self.impulse == 2 && (self.secondary_items & NIT_SNIPER_RIFLE))
  1891.         TeamFortress_SniperWeapon();
  1892.     // The Assault cannon replaces the rocket launcher
  1893.     if (self.impulse == 7 && (self.secondary_items & NIT_ASSAULT_CANNON))
  1894.         TeamFortress_AssaultWeapon();
  1895.  
  1896.     if (self.impulse >= 1 && self.impulse <= 8)
  1897.         W_ChangeWeapon ();
  1898.  
  1899.     if (self.impulse == 10)
  1900.         CycleWeaponCommand ();
  1901.     if (self.impulse == 11)
  1902.         ServerflagsCommand ();
  1903.  
  1904.     // TeamFortress Inventory
  1905.     if (self.impulse == TF_INVENTORY)
  1906.         TeamFortress_Inventory();
  1907.     // TeamFortress Show Toggleflag State
  1908.     if (self.impulse == TF_SHOWTF)
  1909.         TeamFortress_ShowTF();
  1910.  
  1911.     // TeamFortress Multiskin
  1912.     if ((self.impulse == TF_SKIN_NEXT) && (toggleflags & TFLAG_SKIN))
  1913.         Multiskin_NextSkin();
  1914.     if ((self.impulse == TF_SKIN_PREV) && (toggleflags & TFLAG_SKIN))
  1915.         Multiskin_PrevSkin();
  1916.  
  1917.     // TeamFortress Prime Grenade Type 1
  1918.     if (self.impulse == TF_GRENADE_1)
  1919.         TeamFortress_PrimeGrenade();
  1920.     // TeamFortress Prime Grenade Type 2
  1921.     if (self.impulse == TF_GRENADE_2)
  1922.         TeamFortress_PrimeGrenade();
  1923.     // TeamFortress Throw Grenade 
  1924.     if (self.impulse == TF_GRENADE_T)
  1925.         TeamFortress_ThrowGrenade();
  1926.  
  1927.     // TeamFortress Detonate Pipebmombs
  1928.     if (self.impulse == TF_PB_DETONATE)
  1929.         TeamFortress_DetonatePipebombs();
  1930.  
  1931.     // TeamFortress Change PlayerClass
  1932.     if (self.impulse >= TF_CHANGEPC && self.impulse < TF_CHANGEPC + PC_LASTCLASS )
  1933.         TeamFortress_ChangeClass();
  1934.  
  1935.     // TeamFortress Pre-Impulse Commands
  1936.     if (self.impulse == TF_DETPACK)
  1937.         self.last_impulse = self.impulse;
  1938.     if (self.impulse == TF_SCAN)
  1939.         self.last_impulse = self.impulse;
  1940.     if (self.impulse == TF_HELP)
  1941.     {
  1942.         // If it's not a multiplayer game, point out the pre-impulse limitations
  1943.         if (coop || deathmatch)
  1944.             self.last_impulse = self.impulse;
  1945.         else
  1946.         {
  1947.             sprint(self, "N.B. You are playing a single-player game. Some ");
  1948.             sprint(self, "aliases, such as the help aliases, do not work in ");
  1949.             sprint(self, "single-player unless you bind them to a key.\n");
  1950.             sprint(self, "We suggest you start a multiplayer cooperative game ");
  1951.             sprint(self, "and play on your own.\n");
  1952.             sprint(self, "For more info on this, read the readme.txt\n");
  1953.         }
  1954.     }
  1955.     if (self.impulse == TF_TOGGLE)
  1956.         self.last_impulse = self.impulse;
  1957.     if (self.impulse == TF_MULTISKIN)
  1958.         self.last_impulse = self.impulse;
  1959.     if (self.impulse == TF_TEAM)
  1960.         self.last_impulse = self.impulse;
  1961.         
  1962.     self.impulse = 0;
  1963. };
  1964.  
  1965. /*
  1966. ============
  1967. W_WeaponFrame
  1968.  
  1969. Called every frame so impulse events can be handled as well as possible
  1970. ============
  1971. */
  1972. void() W_WeaponFrame =
  1973. {
  1974.     if (time < self.attack_finished)
  1975.         return;
  1976.  
  1977.     // Stop calling this function so much
  1978.     if (self.impulse == TF_ALIAS_CHECK)
  1979.         return;
  1980.     if (self.impulse != 0)
  1981.         ImpulseCommands ();
  1982.  
  1983.     // check for attack
  1984.     if (self.button0)
  1985.     {
  1986.         // check for undefined player changing camera points
  1987.         if (self.playerclass == PC_UNDEFINED)
  1988.         {
  1989.             // stop player from continuously cycling through all the points too fast
  1990.             if (self.weaponmode == 0)
  1991.             {
  1992.                 TF_MovePlayer();
  1993.                 self.weaponmode = 1;
  1994.             }
  1995.     
  1996.             return;
  1997.         }
  1998.  
  1999.         if (self.weapon != IT_EXTRA_WEAPON && self.secondary_weapon != NIT_ASSAULT_CANNON)
  2000.         {
  2001.             SuperDamageSound ();
  2002.             W_Attack ();
  2003.         }
  2004.         else
  2005.         {
  2006.             // Only fire the Assault Cannon if the player is on the ground
  2007.             if (self.flags & FL_ONGROUND)
  2008.             {
  2009.                 SuperDamageSound ();
  2010.                 W_Attack ();
  2011.             }
  2012.         }
  2013.     }
  2014.     else if (self.playerclass == PC_UNDEFINED)
  2015.     {
  2016.         self.weaponmode = 0;
  2017.     }
  2018. };
  2019.  
  2020. /*
  2021. ========
  2022. SuperDamageSound
  2023.  
  2024. Plays sound if needed
  2025. ========
  2026. */
  2027. void() SuperDamageSound =
  2028. {
  2029.     if (self.super_damage_finished > time)
  2030.     {
  2031.         if (self.super_sound < time)
  2032.         {
  2033.             self.super_sound = time + 1;
  2034.             sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
  2035.         }
  2036.     }
  2037.     return;
  2038. };
  2039.  
  2040.  
  2041.